#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include "Listener.h"

     int listen_socket, client_socket;
     int serverport=3334;
     socklen_t clilen;
     char buffer[256];
     struct sockaddr_in serverAdress, clientAdress;
     int n,result;
     pid_t processid;
     int childcount = 0;
 


void error(const char *msg)
{
    perror(msg);
    exit(1);
}

void processoFilho()
{
    close(listen_socket);
  				//loop until client closes
    int i;
    char* t1;
    char* arg[300];

    while (1){
        
        //Ler menssagem recebida
        bzero(buffer,256);
        n = read(client_socket,buffer,255);
        if (n == 0) error("ERROR reading from socket");
        printf("Here is the message: %s\n",buffer);

        t1 = strtok (buffer, " ");
        while (t1 != NULL){
            for(i=1;i<6;i++) {
                 arg[i]=t1;
                t1 = strtok (NULL, " ");
            }
        }

        char* funcao = arg[1];
        char* medicamento = arg[2];
        char* stock = arg[3];

        printf(" funcao: %s\n",funcao);
        printf(" medicamento: %s\n",medicamento);
        printf(" stock: %s\n",stock);


        

        //chamar funcao

        if(strcmp("insere_medicamento", funcao)==0)
        {
            char dados[100];
            strcpy (dados,medicamento);
            strcat (dados," ");
            strcat (dados,stock);
            inserir(dados);
            //write(client_socket,"A inserir...", 25);
        }else{
        
        if(strcmp("eliminar_medicamento", funcao)==0)
        {
             apagar(medicamento);
             //write(client_socket,"A eliminar...", 25);
        }else{

        if(strcmp("efectuar_compra", funcao)==0)
        {
            char dados[100];
            strcpy (dados,medicamento);
            strcat (dados," ");
            strcat (dados,stock);
            comprar(dados);
            //write(client_socket,"A actualizar...", 25);
        }else{

        if(strcmp("ler_medicamento", funcao)==0)
        {
             pesquisar(medicamento);
             //write(client_socket,"A ler...", 25);
        }else{

        if(strcmp("top_vendas", funcao)==0)
        {
             topvendas();
            // write(client_socket,"A aceder ao stock...", 25);
        }else{
            write(client_socket,"Funcao nao existente", 25);
        }}}}}
        

        if (n < 0) error("ERROR writing to socket");
    }
    

    //o filho sai da aplicacao
    close(client_socket);
    exit(0);
}

void processoPai()
{
    //incrementar  o número de filhos
    childcount++;
    while(childcount){
            processid = waitpid( (pid_t) - 1, NULL, WNOHANG );
            if (processid < 0) error("waitpid()");
            else childcount--;
    }
}


int main()
{

     //abrir a socket
     listen_socket = socket(AF_INET, SOCK_STREAM, 0);
     if (listen_socket < 0)
        error("ERROR opening socket");

     //definir os atributos do endereço do servidor
     bzero((char *) &serverAdress, sizeof(serverAdress));
     serverAdress.sin_family = AF_INET;
     serverAdress.sin_addr.s_addr = INADDR_ANY;
     serverAdress.sin_port = htons(serverport);

     //fazer o bind da socket com o numero da porta
     if (bind(listen_socket, (struct sockaddr *) &serverAdress, sizeof(serverAdress)) < 0)
              error("ERROR on binding");

     //escutar por conecções
     listen(listen_socket,5);

     //Ciclo infinito para tratar das coneccoes
     while (1){

     //Aceitar coneccao de um cliente
     clilen = sizeof(clientAdress);
     client_socket = accept(listen_socket, (struct sockaddr *) &clientAdress, &clilen);
     if (client_socket < 0)
          error("ERROR on accept");

     //Criar um 'filho' deste processo para atender o cliente recem-conectado
     processid = fork();
     switch(processid){
         case (-1):
             error("ERROR reading from socket");
             break;

         case (0):
             processoFilho();
             break;

         default:
             processoPai();
             break;
     }



     }

     //desligar o servidor
     close(listen_socket);
     return 0;
}

